package com.imooc.news_manager_project.service.impl;

import com.imooc.news_manager_project.common.CommonMethods;
import com.imooc.news_manager_project.common.Result;
import com.imooc.news_manager_project.common.enums.RoleEnum;
import com.imooc.news_manager_project.domain.News;
import com.imooc.news_manager_project.dto.NewsDTO;
import com.imooc.news_manager_project.mapper.NewsRepository;
import com.imooc.news_manager_project.query.NewsQuery;
import com.imooc.news_manager_project.service.INewsService;
import com.imooc.news_manager_project.utils.KeyHandleUtil;
import com.imooc.news_manager_project.utils.RedisUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Service
public class NewsServiceImpl implements INewsService {

    @Autowired
    private NewsRepository newsRepository;
    @Autowired
    private CommonMethods commonMethods;
    @Autowired
    private RedisUtil redisUtil;

    @Override
    public List<News> getAllNews() {
        return newsRepository.findAll();
    }

    @Override
    public Result save(HttpServletRequest request, NewsDTO newsDTO) {
        Map map = commonMethods.getLoginUserInfo(request);
        System.out.println(map);
        if (map != null && !map.get("role").equals(RoleEnum.REPORTER.toString())) {
            return new Result(401, "只有新闻记者才能新增新闻");
        }
        News news = new News();
        BeanUtils.copyProperties(newsDTO, news);
        news.setId(null).setCreateTime(new Date()).setAuthId((Integer) map.get("id"));
        newsRepository.insert(news);
        if (news.getId() != null) {
            return new Result(200, "保存成功", news.getId());
        }
        return new Result(500, "保存失败");
    }


    @Override
    public Result getById(String id) {
        Optional<News> newsOption = newsRepository.findById(id);
        if (newsOption.isPresent()) {
            News news = newsOption.get();
            String keyNews = "news_visitor" + news.getId();
            Long num = redisUtil.incrementValue(keyNews);
            news.setNumVisitor(num);
            return new Result(200, "获取成功", news);
        } else {
            return new Result(404, "新闻不存在");
        }
    }

    @Override
    public Result listByParams(String title) {

        News news = new News();
        if (title != null) {
            news.setTitle(title.trim());
        }
        ExampleMatcher exampleMatcher = ExampleMatcher.matching().withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);
        Example<News> example = Example.of(news, exampleMatcher);
        List<News> newsList = newsRepository.findAll(example);
        return new Result(200, "获取成功", newsList);
    }


    public Result listByParams(NewsQuery newsQuery) {
        News news = new News();
        if (newsQuery.getTitle() != null) {
            news.setTitle(newsQuery.getTitle());
        }

        ExampleMatcher exampleMatcher = ExampleMatcher.matching().withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);
        Example<News> example = Example.of(news, exampleMatcher);
        List<News> newsList = newsRepository.findAll(example);

        return new Result(200, "获取成功", newsList);
    }

    @Override
    public Result update(HttpServletRequest request, NewsDTO newsDTO) {
        Optional<News> newsOptional = newsRepository.findById(newsDTO.getId());
        if (newsOptional.isPresent()) {
            News news = newsOptional.get();
            Map map = commonMethods.getLoginUserInfo(request);
            Integer userId = (Integer) map.get("id");
            if (userId.equals(news.getAuthId())) {
                BeanUtils.copyProperties(newsDTO, news);
                newsRepository.save(news);
                return new Result(200, "更新成功");
            }
            return new Result(401, "只有新闻作者才能修改新闻");
        }
        return new Result(404, "新闻不存在");
    }

    @Override
    public Result remove(HttpServletRequest request, String id) {
        Optional<News> newsOptional = newsRepository.findById(id);
        if (newsOptional.isPresent()) {
            News news = newsOptional.get();
            Map map = commonMethods.getLoginUserInfo(request);
            String roleCurrent = (String) map.get("role");
            Integer userId = (Integer) map.get("id");
            if (roleCurrent.equals(RoleEnum.ADMIN.toString()) || userId.equals(news.getAuthId())) {
                newsRepository.deleteById(id);
                return new Result(200, "删除成功");
            } else {
                return new Result(401, "只有新闻作者和管理员才能删除新闻");
            }
        } else {
            return new Result(404, "新闻不存在");
        }
    }


    public Result likesById(HttpServletRequest request, String id) {
        String msg = "";
        // 验证是否存在对应id新闻数据
        Optional<News> optionalNews = newsRepository.findById(id);
        if (optionalNews.isPresent()) {
            //	获取当前登录用户的信息
            Map map = commonMethods.getLoginUserInfo(request);
            Integer userId = (Integer) map.get("id");
            //	定义 redis 新闻点赞数据的key值格式
            // String key = "news_likes_" + id;
            String key = KeyHandleUtil.handleNewsLikeKey(id);
            boolean haveKey = redisUtil.hasKey(key);
            if (!haveKey) {
                //	该新闻第一次点赞，保存点赞数据
                redisUtil.addSet(key, userId);
                msg = "点赞成功";
            } else {
                //	判断该用户是点赞还是取消点赞
                boolean resHava = redisUtil.hasMemberSet(key, userId);
                if (resHava) {
                    //	如果已经点过赞，则进行取消点赞
                    redisUtil.removeSet(key, userId);
                    msg = "取消点赞成功";
                } else {
                    redisUtil.addSet(key, userId);
                    msg = "点赞成功";
                }
            }
            Long resNum = redisUtil.countSet(key);
            return new Result(200, msg, resNum);
        } else {
            return new Result(400, "不存在对应id的新闻数据");
        }
    }
}
